// *************************************
// * Creator:SunnyPaine
// * DateTime:2024/08/09 10:08:11
// * Description:<Description>
// * CopyRight:
// * ***********************************

using System;
using System.Windows.Input;
using SunnyPaine.Autofac.Extension.Mvvm.Utils;

namespace SunnyPaine.Autofac.Extension.Mvvm.Commands
{
    /// <summary>
    /// 交互命令的基础逻辑。
    /// </summary>
    /// <typeparam name="T">命令的参数类型。</typeparam>
    public abstract class BaseCommand<T> : ICommand<T>
    {
        #region 保护变量
        /// <summary>
        /// 命令关联的方法。
        /// </summary>
        protected Action<T> executeMethod;
        /// <summary>
        /// 命令关联的是否可执行方法。
        /// </summary>
        protected Func<T, bool> canExecuteMethod;
        #endregion


        #region 事件委托
        /// <summary>
        /// 当命令是否可执行状态变化时发生。
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        #endregion


        #region 私有方法
        /// <summary>
        /// 获取命令方法的参数。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        /// <exception cref="InvalidCastException"></exception>
        private static T GetParameter(object parameter)
        {
            parameter = TypeConverterUtil.Convert(parameter, typeof(T));
            if (parameter == null || parameter is T)
            {
                return (T)parameter;
            }

            throw new InvalidCastException($"命令的参数无法从 {parameter.GetType().FullName} 转换到 {typeof(T).FullName}");
        }
        #endregion


        #region 私有方法，ICommand成员
        bool ICommand.CanExecute(object parameter)
        {
            return this.CanExecute(GetParameter(parameter));
        }

        void ICommand.Execute(object parameter)
        {
            this.Execute(GetParameter(parameter));
        }
        #endregion


        #region 公共方法，ICommand<T>成员
        /// <summary>
        /// 是否可执行命令的校验。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(T parameter)
        {
            return this.canExecuteMethod == null || this.canExecuteMethod(parameter);
        }

        /// <summary>
        /// 执行命令。
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(T parameter)
        {
            if (this.CanExecute(parameter) && this.executeMethod != null)
            {
                this.executeMethod(parameter);
            }
        }
        #endregion
    }
}